package com.bbva.kyfb.kyfbbofi.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.bbva.jee.arq.spring.core.contexto.ArqSpringContext;
import com.bbva.jee.arq.spring.core.gce.CodigoError;
import com.bbva.jee.arq.spring.core.gce.ExcepcionEjecucionAplicacion;
import com.bbva.jee.arq.spring.core.log.I18nLog;
import com.bbva.jee.arq.spring.core.log.I18nLogFactory;
import com.bbva.jee.arq.spring.core.util.excepciones.PropiedadNoEncontradaExcepcion;
import com.bbva.jee.arq.spring.core.util.excepciones.PropiedadNoParseableExcepcion;
import com.bbva.kyfb.kyfbbofi.IFirmasBo;
import com.bbva.kyfb.kyfbbofi.ServicioFirmasBoAsistenteUtil;
import com.bbva.kyfb.kyfbbofi.ServicioFirmasBoClientsUtil;
import com.bbva.kyfb.kyfbbofi.ServicioFirmasBoHostUtil;
import com.bbva.kyfb.kyfbbofi.ServicioFirmasBoUtil;
import com.bbva.kyfb.kyfbbofi.pau.ISrvAutenticacionPAU;
import com.bbva.kyfb.kyfbdaofi.IFirmasDao;
import com.bbva.kyfb.kyfbdto.firmas.bo.AsuntoInfo;
import com.bbva.kyfb.kyfbdto.firmas.bo.Auditoria;
import com.bbva.kyfb.kyfbdto.firmas.bo.ComponenteFirmable;
import com.bbva.kyfb.kyfbdto.firmas.bo.ComponentePutFirma;
import com.bbva.kyfb.kyfbdto.firmas.bo.ConsultaEmpresaAsociadasNifDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.ConsultaEmpresaAsociadasRefDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.DatosPAU;
import com.bbva.kyfb.kyfbdto.firmas.bo.DeletedFilesDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.EmpresaNifOutDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.EmpresaRefOutDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo;
import com.bbva.kyfb.kyfbdto.firmas.bo.FicheroPdteFirma;
import com.bbva.kyfb.kyfbdto.firmas.bo.FirmaComponente;
import com.bbva.kyfb.kyfbdto.firmas.bo.FirmanteInfo;
import com.bbva.kyfb.kyfbdto.firmas.bo.InfoAssistantDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.InfoComponentDetailDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.InfoComponentInDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.InfoOrdenInDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.ListNData;
import com.bbva.kyfb.kyfbdto.firmas.bo.Listado;
import com.bbva.kyfb.kyfbdto.firmas.bo.NotificacionOutDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.ObjetoFirmable;
import com.bbva.kyfb.kyfbdto.firmas.bo.OrdenMifidInDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.OrdenMifidOutDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.ReferenciaInfo;
import com.bbva.kyfb.kyfbdto.firmas.bo.ServicioAsuntoFirmable;
import com.bbva.kyfb.kyfbdto.firmas.bo.ServicioInfo;
import com.bbva.kyfb.kyfbdto.firmas.bo.UpdateInfoInDto;
import com.bbva.kyfb.kyfbdto.firmas.bo.UpdateInfoOutDto;
import com.bbva.kyfb.kyfbdto.firmas.errores.Errores_kyfb_servicios;
import com.bbva.kyfb.kyfbdto.firmas.fachada.v01.SignedComponentsResponse;
import com.bbva.kyfb.kyfbdto.firmas.filtros.FilesDeleteInfo;
import com.bbva.kyfb.kyfbdto.firmas.filtros.FiltroFicheros;
import com.bbva.kyfb.kyfbdtofo.FicheroRequest;
import com.bbva.kyfb.kyfbdtofo.fachada.interfaces.v01.ExecuteServiceV01;
import com.bbva.kyfb.kyfbjpatlbh.dominiotlbh.Ttlsbfua;
import com.bbva.kyfb.kyfbjpatlbh.dominiotlbh.Ttlsbsfo;
import com.bbva.kyfb.kyfbjpatlbh.dominiotlbh.TtlsbsfoPK;
import com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Ttlsbffs;
import com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.TtlsbffsPK;
import com.bbva.kyfb.kyfbofi.converters.ResulSetDtoConverter;
import com.bbva.kyfb.kyfbutils.constantes.ConstantesFO;
import com.bbva.kyfb.kyfbutils.constantes.UtilFO;
import com.bbva.kyfb.kyfbutils.dao.DaoUtils;
import com.bbva.kyfb.kyfbutils.errores.ValidationUtils;
import com.bbva.kyfb.kyfbutils.host.Constants;
import com.bbva.kyfb.kyfbutils.invoker.InvokerUtils;
import com.bbva.kyfb.kyfbutils.mifid.MifidFunctions;
import com.bbva.kyfb.kyfbutils.pau.ConstantesPAU;
import com.bbva.kyfb.kyfbutils.pau.FuncionesPAU;
import com.bbva.kygu.clientcontractws.beans.AStringsType;
import com.bbva.kygu.clientcontractws.beans.ServicioAsuntosType;
import com.bbva.kygu.clientcontractws.beans.UsuarioServAsuntoType;
import com.bbva.kytv.dto.kygu.UsuarioEmpresaDTO;
import com.bbva.kytv.dto.kyud.InformacionServicioIndicadorDTO;
import com.bbva.kytv.dto.kyud.RespuestaServicioIndDTO;
import com.bbva.kytv.interfaces.kygu.IServicioInformacionServicios;
import com.bbva.kytv.util.exception.KYTVException;

/**
 * The Class ServicioFirmasBoImpl.
 */
@Component(value = "servicioFirmasBo")
public class ServicioFirmasBoImpl implements IFirmasBo {

	/** Variable LOG. */
	private static final I18nLog LOG = I18nLogFactory
			.getLogI18n(ServicioFirmasBoImpl.class);

	/** The servicio firmas dao. */
	@Autowired
	private IFirmasDao servicioFirmasDao;

	/** The servicio firmas bo util. */
	@Autowired
	private ServicioFirmasBoUtil servicioFirmasBoUtil;

	/** The servicio firmas bo host util. */
	@Autowired
	private ServicioFirmasBoHostUtil servicioFirmasBoHostUtil;

	/** The servicio firmas bo host util. */
	@Autowired
	private ServicioFirmasBoAsistenteUtil servicioFirmasBoAsistenteUtil;

	/** The servicio firmas bo util. */
	@Autowired
	private ServicioFirmasBoClientsUtil servicioFirmasBoClientsUtil;

	/** The srv autenticador pau. */
	@Autowired
	private ISrvAutenticacionPAU srvAutenticadorPAU;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final List<FicheroPdteFirma> getComponentesPendientesReferencia(
			final FicheroInfo file) {
		final FiltroFicheros filtro = servicioFirmasBoUtil.createFiltroFromDto(file);
		final boolean hasCodUsuario = filtro.getCodUsuario() != null;
		final List<FicheroPdteFirma> resultado = ResulSetDtoConverter
				.createFicherosPdteDtoFromEntity(servicioFirmasDao
						.findComponentesPdteReferencia(
								file.getCodClienteCash(),
								file.getCodAplicacion(), filtro, hasCodUsuario));
		return resultado;
	}

	/**
	 * {@inheritDoc}
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getComponentesPendientesReferencia(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo)
	 */
	@Override
	public final int getTotalComponentesPdtesReferencia(final FicheroInfo file,final String[] timeStamps) {
		final FiltroFicheros filtro = servicioFirmasBoUtil.createFiltroFromDto(file);
		final boolean hasCodUsuario = filtro.getCodUsuario() != null;
		final int total;

		if(ConstantesFO.SIGLAS_FIRMA_SERVIDOR.equalsIgnoreCase(file.getStipoFirma())){
			total = servicioFirmasDao.getTotalComponentesPdtesReferencia(
					file.getCodClienteCash(), file.getCodAplicacion(), filtro, hasCodUsuario);
		}else{
			total = servicioFirmasBoHostUtil.getTotalComponentesPdtesReferenciaHost(file,filtro,hasCodUsuario,timeStamps);
		}

		return total;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final List<FicheroPdteFirma> getComponentesPendientesReferenciaUsuario(
			final FicheroInfo file) throws ExcepcionEjecucionAplicacion {

		final List<FicheroPdteFirma> resultadoParaUsuario = new ArrayList<FicheroPdteFirma>();

		final FiltroFicheros filtro = servicioFirmasBoUtil.createFiltroFromDto(file);
		final boolean hasCodUsuario = filtro.getCodUsuario() != null;
		final List<FicheroPdteFirma> lstFchPteFirma = ResulSetDtoConverter
				.createFicherosPdteDtoFromEntity(servicioFirmasDao
						.findComponentesPdteReferenciaUsuario(
								file.getCodClienteCash(),
								file.getCodAplicacion(), filtro, hasCodUsuario));

		final String tipoFirmante = servicioFirmasBoClientsUtil.getTipoFirmante(file);

		final List<ServicioAsuntoFirmable> listaServiciosAsuntosFirmables;
		final Map<String, ServicioInfo> clasesOrdIdServicio;
		// recuperamos los servicios por asunto firmables por usuario si este es
		// != de AUDITOR
		if (!tipoFirmante.equals(UtilFO.USUARIO_AUDITOR)) {
			listaServiciosAsuntosFirmables = servicioFirmasBoClientsUtil
					.getAsuntosServicioByUsuario(file);
			clasesOrdIdServicio = getClasesOrdenesByCodServicio(
					listaServiciosAsuntosFirmables,
					Integer.parseInt(file.getCodClienteCash().substring(4, 8)));
		} else {
			listaServiciosAsuntosFirmables = new ArrayList<ServicioAsuntoFirmable>();
			clasesOrdIdServicio = new HashMap<String, ServicioInfo>();
		}

		// Vamos a obtener una hashmap<String, Double> con los cambios de tipo
		// de divisa
		final Map<String, Double> tiposDeCambio = servicioFirmasDao.findTiposDeCambio(
				Integer.parseInt(file.getCodClienteCash().substring(4, 8)));
		// Vamos a buscar el listado de ficheros firmados por el usuario
		final List<String> listadoFirmados = servicioFirmasDao.findFirmasRealizasByUsuario(file);
		// Conseguimos la relacion entre qNuItem y numeros aleatorios
		final Map<String, String> ficheroNumAleatorio = servicioFirmasDao.findFicherosNumAleatorio(
				file.getsCodUsuario(),file.getCodClienteCash().substring(8, 16));
		// Evaluamos la Lista de Ordenes (Array de Ficheros, Ej: NOM-123,
		// REC-123, TRA-123
		for (final FicheroPdteFirma fichero : lstFchPteFirma) {
			// Comprobamos si el usuario ya ha firmado este fichero
			if (!listadoFirmados.contains(fichero.getNumItem())) {
				// Al estar pendiente de firma o firmado parcialmente,
				// comprobamos si esta dentro de los servicios firmables y si el
				// asunto del fichero coincide
				// con uno de los del servicio servicio
				if (fichero.getsCodEstadoFichero().equalsIgnoreCase(UtilFO.EST_PDTE_FIRMA)
						|| fichero.getsCodEstadoFichero().equalsIgnoreCase(UtilFO.EST_FDO_PARCIAL)) {
					// Si esta pendiente de firma o firmado parcialmente,
					// y el usuario es un APODERADO, continuamos con la
					// validacion de ficheros
					if (!tipoFirmante.equals(UtilFO.USUARIO_AUDITOR)
							// Es APODERADO, se comprobara limites y asuntos
							&& clasesOrdIdServicio.containsKey(fichero.getCodigoServicioGlobal())) {
						// Comprobamos que el tipo de orden del fichero esta
						// en la lista de servicios firmables por el usuario
						final ServicioInfo codigoServicio = clasesOrdIdServicio.get(fichero.getCodigoServicioGlobal());

						for (final ServicioAsuntoFirmable sServicioFirmable : listaServiciosAsuntosFirmables) {
							// Recorremos el listado de servicios firmables
							// por el usuario, para recoger el que coincide
							// con el fichero procesado
							if (sServicioFirmable.getTipoServicio()
									.equalsIgnoreCase(codigoServicio.getCodigoServicioLocal())) {
								// Si coincide, recorreremos el listado de
								// asuntos
								final String asuntoTransformado;
								if (fichero.getModoOrden().equalsIgnoreCase(
										ConstantesFO.ORDEN_ONLINE)) {
									asuntoTransformado = servicioFirmasBoClientsUtil
											.transformarAsunto(fichero,file);
								} else {
									asuntoTransformado = fichero.getsAsunto();
								}

								for (final AsuntoInfo asuntoFirmable : sServicioFirmable.getAsuntos()) {
									boolean limiteOK = false;
									final boolean asuntoOK = asuntoFirmable.getAsunto().equalsIgnoreCase(asuntoTransformado)
											&& codigoServicio.getValidarAsunto().equalsIgnoreCase("S")
											|| codigoServicio.getValidarAsunto().equalsIgnoreCase("N");

									double importeMaxRegistro = fichero.getImporteMaximoRegistro();

									if (!asuntoFirmable.getDivisa().isEmpty()
											&& !fichero.getsDivisa().isEmpty()
											&& !asuntoFirmable.getDivisa().equalsIgnoreCase(fichero.getsDivisa())
											// Las divisas son diferentes de "" y son diferentes entre si
											&& tiposDeCambio.containsKey(asuntoFirmable.getDivisa())
											&& tiposDeCambio.containsKey(fichero.getsDivisa())) {
										// Calculamos factores y aplicamos el tipo de cambio
										importeMaxRegistro *= tiposDeCambio.get(asuntoFirmable.getDivisa());
										importeMaxRegistro /= tiposDeCambio.get(fichero.getsDivisa());
									}

									if (importeMaxRegistro <= asuntoFirmable.getLimite()
											&& codigoServicio.getValidarLimite().equalsIgnoreCase("S")
											|| codigoServicio.getValidarLimite().equalsIgnoreCase("N")) {
										// Ahora comprobamos la DIVISA

										limiteOK = !UtilFO.esZonaEuro(fichero.getsCodTipoOrden()) ||
												asuntoFirmable.getDivisa().equalsIgnoreCase(fichero.getsDivisa());
									}
									if (asuntoOK && limiteOK) {
										// Si se superan las validaciones,
										// anadimos fichero al resultado
										fichero.setsPoderFirma(sServicioFirmable
												.getPoderFirma());
										// Vamos a verificar y asignar el numero aleatorio antes de insertar el fichero en el resultado
										servicioFirmasBoUtil.comprobarAsignacionNumeroAleatorio(fichero, ficheroNumAleatorio);
										resultadoParaUsuario.add(fichero);
										break;
									}
								}
							}
						}
					}

				} else if (fichero.getsCodEstadoFichero().equals(
						UtilFO.EST_PDTE_AUDITOR)
						&& tipoFirmante.equals(UtilFO.USUARIO_AUDITOR)) {
					// Los auditores siempre firman como solidarios
					fichero.setsPoderFirma(UtilFO.FIRMA_SOLIDARIO);
					// Vamos a verificar y asignar el numero aleatorio antes de insertar el fichero en el resultado
					servicioFirmasBoUtil.comprobarAsignacionNumeroAleatorio(fichero, ficheroNumAleatorio);
					resultadoParaUsuario.add(fichero);

				}
			}
		}

		DaoUtils.atLeastOneRecord(resultadoParaUsuario);

		return resultadoParaUsuario;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getComponentesPendientesReferenciaUsuarioHost(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo)
	 */
	@Override
	public final Listado<FicheroPdteFirma> getComponentesPendientesReferenciaUsuarioHost(
			final FicheroInfo file) throws ExcepcionEjecucionAplicacion {

		final List<FicheroPdteFirma> fichPendtes;

		final Listado<FicheroPdteFirma> lstFichPndts = new Listado<FicheroPdteFirma>();

		// Recuperamos las clases de ordenes firmables desde la aplicacion de
		// origen
		final List<ComponenteFirmable> firmablesAplicacion = ResulSetDtoConverter
				.createComponentesFirmables(servicioFirmasDao
						.findFirmablesAplicacion(file.getCodAplicacion()
								.toUpperCase()));
		// Comprobamos tipos de ordenes que nos pasan, si no pasan ninguna no se
		// filtra y se devuelven todas.
		if (file.getsTipoOrden() != null && file.getsTipoOrden().length != 0) {
			for (final Iterator<ComponenteFirmable> iter = firmablesAplicacion.iterator();iter.hasNext();) {
				final ComponenteFirmable compFir = iter.next();
				if (Arrays.binarySearch(file.getsTipoOrden(), compFir.getTipoOrden())<0){
					iter.remove();
				}
			}
		}

		// Recuperamos hash de numeros aleatorios
		final Map<String, String> ficheroNumAleatorio = servicioFirmasDao.findNumAleatorioFRFbyUsuario(file.getsNifDni());

		List<String> idComponentes = servicioFirmasBoHostUtil.getIdsComponentes(file);
		if (!idComponentes.isEmpty()){
			// Parseamos fechas
			try {
				idComponentes = UtilFO.convertirFechasTxToBBDD(idComponentes);
			} catch (final ParseException ex) {
				LOG.error("ServicioFirmasBoImpl - Se ha producido un error al parsear la fechas.",ex);
				throw new ExcepcionEjecucionAplicacion(Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE,ex);
			}

			final String[] listaId = new String[idComponentes.size()];

			final FiltroFicheros filtro = servicioFirmasBoUtil.createFiltroFromDto(file);
			final boolean hasCodUsuario = filtro.getCodUsuario() != null;

			fichPendtes = ResulSetDtoConverter.createFicherosPdteDtoFromEntity(
					servicioFirmasDao.findComponentesPdteReferenciaTimFichero(
							file.getCodClienteCash(), file.getCodAplicacion(), filtro,hasCodUsuario,idComponentes.toArray(listaId)));

			lstFichPndts.setTotal(servicioFirmasDao.countComponentesPdteReferenciaTimFichero(
					file.getCodClienteCash(), file.getCodAplicacion(), filtro,hasCodUsuario,idComponentes.toArray(listaId)));

			// Vamos a setear el numero aleatorio en caso de que exista
			for (final FicheroPdteFirma firmante : fichPendtes) {
				final String fechaCreacion = StringUtils.rightPad(new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS").format(firmante.getdFechaCreacion()).toString(), Constants.FORMATO_TIMESTAMPSOLIC_MIN_LENGTH, '0');
				if (ficheroNumAleatorio.containsKey(fechaCreacion)) {
					// Devolvemos el numero aleatorio
					firmante.setsNumeroAleatorio(ficheroNumAleatorio.get(fechaCreacion));
				} else {
					// No existe, luego se devuelve blanco
					firmante.setsNumeroAleatorio("");
				}
			}
		} else {
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR);
		}

		lstFichPndts.setLista(fichPendtes);


		return lstFichPndts;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getAuditoriaComponentePendientes(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo)
	 */
	@Override
	public final List<Auditoria> getAuditoriaComponentePendientes(final FicheroInfo file)
			throws ExcepcionEjecucionAplicacion {
		final List<Auditoria> resultado = ResulSetDtoConverter
				.createAuditoriasDtoFromEntity(servicioFirmasDao
						.findAuditoriaComponentePdte(file.getCodClienteCash(),
								file.getsTipoOrden()[0], file.getIdOrden(),
								file.getsCodEstado()));
		return resultado;
	}

	@Override
	public final FicheroPdteFirma getFicheroPdteFirma(final FicheroInfo file){
		final FiltroFicheros filtro = servicioFirmasBoUtil.createFiltroFromDto(file);
		final boolean hasCodUsuario = filtro.getCodUsuario() != null;
		return ResulSetDtoConverter.createFicherosPdteDtoFromEntity(servicioFirmasDao.findComponentesPdteReferencia(file.getCodClienteCash(), file.getCodAplicacion(), filtro, hasCodUsuario)).get(0);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getUsuariosFirmaPedte(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo)
	 */
	@Override
	public final List<FirmanteInfo> getUsuariosFirmaPedte(final FicheroInfo file, final FicheroPdteFirma ficheroPdte) throws ExcepcionEjecucionAplicacion {
		final List<FirmanteInfo> listaFirmantes = new ArrayList<FirmanteInfo>();

		final Map<String, String> usuNumAleatorio = servicioFirmasDao.findUsuariosNumAleatorio(BigDecimal
				.valueOf(ficheroPdte.getsNumItem()), file.getCodClienteCash()
				.substring(8, 16));

		if (ficheroPdte.getsCodEstadoFichero().equals(UtilFO.EST_PDTE_AUDITOR)) {
			// El fichero se encuentra en estado Pendiente Auditar, por lo
			// que directamente comprobamos los usuarios auditores
			// para la clase de servicio y asunto
			servicioFirmasBoClientsUtil.addAuditoresToListaFirmantes(file,
					listaFirmantes, ficheroPdte, usuNumAleatorio);

		} else if (ficheroPdte.getsCodEstadoFichero().equals(
				UtilFO.EST_PDTE_FIRMA)) {
			// El fichero se encuentra en estado Pendiente de Firma, por lo
			// que comprobamos los usuario apoderados
			// para la clase de servicio y asunto.
			final List<UsuarioServAsuntoType> listaUsuarios = servicioFirmasBoClientsUtil
					.getApoderadosServicio(ficheroPdte, file,
							file.getCodServicio());
			for (final UsuarioServAsuntoType usuarioApoderado : listaUsuarios) {
				for (final ServicioAsuntosType servAsun : usuarioApoderado
						.getListaServicioAsuntos().getServicioAsuntos()) {
					listaFirmantes.add(createFirmanteInfo(usuarioApoderado,servAsun.getPoderFirma(),usuNumAleatorio,ficheroPdte, file));
				}
			}
		} else if (ficheroPdte.getsCodEstadoFichero().equals(
				UtilFO.EST_FDO_PARCIAL)) {
			// el fichero se encuentra en estado Firmado Parcialmente por lo
			// que recuperamos los usuario que han firmado
			// por un lado, por otro recuperamos quienes tienen permiso para
			// la clase de servicio y asunto, y cruzamos la informacion
			final List<FirmanteInfo> listaFirmantesRealizadas = ResulSetDtoConverter
					.createFirmantesInfo(servicioFirmasDao.findFirmasRealizas(
							file.getIdOrden(), file.getsTipoOrden()[0],
							file.getCodClienteCash()));
			final String codServicio = servicioFirmasDao.findCodProductoByClaseOrd(
					ficheroPdte.getsCodTipoOrden()).get(
							ficheroPdte.getsCodTipoOrden());

			final List<UsuarioServAsuntoType> listaUsuarios = servicioFirmasBoClientsUtil
					.getApoderadosServicio(ficheroPdte, file, codServicio);
			if (listaUsuarios != null && listaUsuarios.size() > 0) {
				final List<FirmanteInfo> listaFirmantesAux = new ArrayList<FirmanteInfo>();
				for (final UsuarioServAsuntoType usuarioApoderado : listaUsuarios) {
					for (final ServicioAsuntosType servAsun : usuarioApoderado
							.getListaServicioAsuntos().getServicioAsuntos()) {
						listaFirmantesAux.add(createFirmanteInfo(usuarioApoderado,servAsun.getPoderFirma(),usuNumAleatorio,ficheroPdte, file));
					}

				}
				for (final FirmanteInfo posibleFirmante : listaFirmantesAux) {
					for (final FirmanteInfo firmante : listaFirmantesRealizadas) {
						if (!posibleFirmante.getCodUsuario().equals(
								firmante.getCodUsuario())) {
							listaFirmantes.add(firmante);
						}
					}
				}
			} else {
				throw new ExcepcionEjecucionAplicacion(
						Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR);
			}
		} else {
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR);
		}

		DaoUtils.atLeastOneRecord(listaFirmantes);
		return listaFirmantes;
	}

	private final FirmanteInfo createFirmanteInfo(final UsuarioServAsuntoType usuApod, final String poderFirma, final Map<String, String> usuNumAleatorio, final FicheroPdteFirma ficheroPdte, final FicheroInfo file){
		final FirmanteInfo apoderado = new FirmanteInfo();
		apoderado.setCodUsuario(usuApod.getCodUsuario());
		apoderado.setsTipoFirma(usuApod.getModoFirma());
		apoderado.setsTipoFirmante(UtilFO.USUARIO_APODERADO);
		apoderado.setPoderFirma(poderFirma);
		apoderado.setsNomUsuario(usuApod.getNomUsuario());
		ficheroPdte.setsPoderFirma(poderFirma);
		apoderado.setNumeroAleatorio(
				servicioFirmasBoUtil.asignarNumeroAleatorio(
						usuNumAleatorio,ficheroPdte, file,apoderado.getCodUsuario()));
		return apoderado;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getUsuariosFirmaRealizada(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo)
	 */
	@Override
	public final List<FirmanteInfo> getUsuariosFirmaRealizada(final FicheroInfo file)
			throws ExcepcionEjecucionAplicacion {
		// String canal = "";
		// String bancoInt = "";
		// String referencia = "";
		// Obtenemos la lista inicial de firmantes
		List<FirmanteInfo> listaFirmantes = ResulSetDtoConverter
				.createFirmantesInfo(servicioFirmasDao.findFirmasRealizas(
						file.getIdOrden(), file.getsTipoOrden()[0],
						file.getCodClienteCash()));

		if (ConstantesFO.SIGLAS_FIRMA_HOST.equalsIgnoreCase(file.getStipoFirma())) {
			// Se trata de firma HOST
			listaFirmantes = servicioFirmasBoHostUtil
					.getUsuariosFirmaRealizada(listaFirmantes, file);
		}/* esto no tiene sentido ya
			else {
			// Se trata de firma SERVIDOR
			// listaFirmantes=
			// createFirmanteInfo(servicioFirmasDao.findFirmasRealizas(file.getIdOrden(),
			// file.getsTipoOrden()[0], file.getCodClienteCash()));
			return listaFirmantes;
		}*/
		return listaFirmantes;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getComponentesFirmables(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo,
	 *      boolean)
	 */
	@Override
	public final List<ComponenteFirmable> getComponentesFirmables(final FicheroInfo file,
			final boolean refAsociadas) throws ExcepcionEjecucionAplicacion {
		List<ComponenteFirmable> listaComponentesFirmablesClases = null;
		ArrayList<ReferenciaInfo> referencias = new ArrayList<ReferenciaInfo>();
		final ArrayList<String> listaClasesOrd = new ArrayList<String>();
		String aux = null;
		// recuperamos clases de ordenes firmables por aplicacion pais
		listaComponentesFirmablesClases = ResulSetDtoConverter
				.createComponentesFirmables(servicioFirmasDao
						.findFirmablesAplicacion(file.getCodAplicacion()
								.toUpperCase()));

		final ReferenciaInfo referenciaPadre = new ReferenciaInfo();
		final String canal = file.getCodClienteCash().substring(0, 4);
		final String bancoInt = file.getCodClienteCash().substring(4, 8);
		final String referencia = file.getCodClienteCash().substring(8, 16);
		referenciaPadre.setCodBancoInt(bancoInt);
		referenciaPadre.setCodCanal(canal);
		referenciaPadre.setReferencia(referencia);
		if (refAsociadas) {
			referencias = (ArrayList<ReferenciaInfo>) servicioFirmasBoClientsUtil
					.getEmpresas(canal, bancoInt, referencia);
		}
		referencias.add(referenciaPadre);
		final List<String> serviciosAsociados = servicioFirmasBoClientsUtil
				.getServiciosAsuntosByEmpresa(referencias);
		final Map<String, String> codServiciosFirmables = servicioFirmasDao
				.findClaseOrdByCodProducto(Arrays.copyOf(
						serviciosAsociados.toArray(),
						serviciosAsociados.toArray().length, String[].class),
						canal, bancoInt);
		for (final Iterator<ComponenteFirmable> iter = listaComponentesFirmablesClases
				.iterator(); iter.hasNext();) {
			final ComponenteFirmable firmable = iter.next();
			if (!codServiciosFirmables.containsKey(firmable.getTipoOrden())) {
				iter.remove();
			} else {
				listaClasesOrd.add(firmable.getTipoOrden());
			}
		}

		final List<Object[]> husosHorarios = servicioFirmasDao.findHusoHorario(Arrays
				.copyOf(listaClasesOrd.toArray(),
						listaClasesOrd.toArray().length, String[].class));
		for (final Object[] husoHorario: husosHorarios) {
			for (final ComponenteFirmable compFirm:listaComponentesFirmablesClases) {
				if (compFirm.getTipoOrden().equals(husoHorario[0])) {
					aux = husoHorario[2] != null ? husoHorario[2].toString() : null;
					compFirm.setHoraCorte(aux == null ? null : aux);
					aux = (String) husoHorario[1];
					compFirm.setTipoCorte(aux == null ? "N" : aux);
					aux = (String) husoHorario[3];
					compFirm.setCodigoServicio(aux == null ? "" : aux);
				}
			}
		}
		return listaComponentesFirmablesClases;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getComponentesFirmables(com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo,
	 *      boolean)
	 */
	@Override
	public final List<ComponenteFirmable> getComponentesFirmables(final FicheroInfo file) {
		// recuperamos clases de ordenes firmables por aplicacion pais
		return ResulSetDtoConverter.createComponentesFirmables(
				servicioFirmasDao.findFirmablesAplicacion(
						file.getCodAplicacion().toUpperCase()));
	}

	/**
	 * Gets the clases ordenes by cod servicio.
	 * 
	 * @param listaServiciosAsuntosFirmables
	 *            the lista servicios asuntos firmables
	 * @param codBancoInterno
	 *            the cod banco interno
	 * @return the clases ordenes by cod servicio
	 */
	private Map<String, ServicioInfo> getClasesOrdenesByCodServicio(
			final List<ServicioAsuntoFirmable> listaServiciosAsuntosFirmables,
			final int codBancoInterno) {
		final Map<String, ServicioInfo> clasesOrdIdServicio = new HashMap<String, ServicioInfo>();
		final Map<String, ServicioInfo> clasesOrdIdRespuesta = new HashMap<String, ServicioInfo>();
		final AStringsType listaServicioG = new AStringsType();
		// Cargamos en memoria la relacion entre codigos de servicio locales y
		// globales
		final Map<String, String> codigosDeServicio = servicioFirmasDao
				.findCodServicioGlobal(codBancoInterno);

		for (final ServicioAsuntoFirmable servAsunto : listaServiciosAsuntosFirmables) {
			// hay que transformar el codigo servicio local al codigo servicio
			// global
			final ServicioInfo value = new ServicioInfo();
			String codigoServicioGlobal;
			if (codigosDeServicio.containsKey(servAsunto.getTipoServicio())) {
				codigoServicioGlobal = codigosDeServicio.get(servAsunto
						.getTipoServicio());
			} else {
				codigoServicioGlobal = servAsunto.getTipoServicio();
			}
			listaServicioG.getItem().add(codigoServicioGlobal);
			value.setCodigoServicioLocal(servAsunto.getTipoServicio());
			value.setCodigoServicioGlobal(codigoServicioGlobal);
			clasesOrdIdServicio.put(value.getCodigoServicioGlobal(), value);
		}

		RespuestaServicioIndDTO res = null;

		try {
			final IServicioInformacionServicios infoServicios = (IServicioInformacionServicios) InvokerUtils.getBeanInvoker(
					ConstantesFO.VAR_INFO_SERV_INVOKER,
					IServicioInformacionServicios.class);
			res = infoServicios.listarServicios(listaServicioG.getItem(), codBancoInterno);
		} catch (final KYTVException e) {
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE, e);
		}

		if (res.getListaServicioInd() != null) {
			for (final InformacionServicioIndicadorDTO aux : res.getListaServicioInd()) {

				final ServicioInfo servicio = clasesOrdIdServicio.get(aux
						.getCodServicio());
				if(servicio!=null){
					servicio.setValidarAsunto(aux.getIndSrvValidacionAsunto());
					servicio.setValidarLimite(aux.getIndSrvValLimGesLim());
					clasesOrdIdRespuesta.put(servicio.getCodigoServicioGlobal(),
							servicio);
				}
			}
		}
		return clasesOrdIdRespuesta;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final NotificacionOutDto sendNotificacion(final DatosPAU datosPAU)
			throws PropiedadNoEncontradaExcepcion {
		final NotificacionOutDto notificacionOutDto = new NotificacionOutDto();
		final String resultado = srvAutenticadorPAU.enviaNotificacion(datosPAU);
		if (resultado != null && resultado.length() > 25) {
			notificacionOutDto.setCodError(String
					.valueOf(Errores_kyfb_servicios.OK));
			notificacionOutDto.setsIdSession(resultado);
		} else {
			notificacionOutDto.setCodError(resultado);
			notificacionOutDto.setsIdSession(null);
		}
		return notificacionOutDto;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @throws PropiedadNoEncontradaExcepcion
	 * @throws NumberFormatException
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getComponenteTipoMifid(com.bbva.kyfb.kyfbdto.firmas.bo.OrdenMifidInDto)
	 */
	@Override
	public final OrdenMifidOutDto getComponenteTipoMifid(
			final OrdenMifidInDto ordenMifidInDto)
					throws ExcepcionEjecucionAplicacion, NumberFormatException,
					PropiedadNoEncontradaExcepcion {

		// Vamos a hacer una llamada al SFO
		final FiltroFicheros filtro = new FiltroFicheros();
		filtro.setIdOrden(ordenMifidInDto.getIdOrdenFirmas());
		final String[] claseOrdenMifid = {ordenMifidInDto.getTipoOrden()};
		filtro.setClaseOrden(claseOrdenMifid);
		final List<FicheroPdteFirma> resultado = ResulSetDtoConverter.createFicherosPdteDtoFromEntity(
				/* Referencia no necesaria para recuperar la orden, soluciona bug ordenes mifid. */
				//servicioFirmasDao.findComponentesPdteReferencia(ordenMifidInDto.getReferencia(), null, filtro, false));
				servicioFirmasDao.findComponentesPdteReferencia(null, null, filtro, false));
		final Double identificador = Double.valueOf(resultado.get(0).getNumItem());
		final boolean esCompra = esCompraMifid(ordenMifidInDto.getTipoOrden(),identificador);
		final boolean esOrdenMifid = MifidFunctions.isOrdenMifid(ordenMifidInDto.getTipoOrden());
		final OrdenMifidOutDto ordenMifidOutDto;

		if (esOrdenMifid && esCompra) {
			ordenMifidOutDto=servicioFirmasBoHostUtil.getComponenteTipoMifid(ordenMifidInDto);
		} else {
			ordenMifidOutDto = new OrdenMifidOutDto();
			ordenMifidOutDto.setTipoMifid("");
		}
		return ordenMifidOutDto;
	}

	/**
	 * Es compra mifid.
	 * 
	 * @param tipoOrden
	 *            the tipo orden
	 * @param identificador
	 *            the identificador
	 * @return true, if successful
	 * @throws ExcepcionEjecucionAplicacion
	 *             the excepcion ejecucion aplicacion
	 * @throws NumberFormatException
	 *             the number format exception
	 * @throws PropiedadNoEncontradaExcepcion
	 *             the propiedad no encontrada excepcion
	 */
	private boolean esCompraMifid(final String tipoOrden, final Double identificador)
			throws ExcepcionEjecucionAplicacion, NumberFormatException,
			PropiedadNoEncontradaExcepcion {
		final boolean esCompra;
		if (MifidFunctions.esOrdenMifidCompraVenta(tipoOrden)) {
			final String numOrden = servicioFirmasDao.findEOOByOrd(tipoOrden, "XTI-OBTIPO");
			final String datosOrden = servicioFirmasDao.findOOLById(identificador);
			final String compra = trocearRespuesta(datosOrden, Integer.parseInt(numOrden));
			esCompra = compra.equalsIgnoreCase(numOrden + "001");
		} else {
			esCompra = false;
		}
		return esCompra;

	}

	/**
	 * Trocear respuesta.
	 * 
	 * @param datosOrden
	 *            the datos orden
	 * @param orden
	 *            the orden
	 * @return the string
	 */
	private String trocearRespuesta(final String datosOrden, final int orden) {

		final StringTokenizer st = new StringTokenizer(datosOrden, "#");
		int contador = 0;
		String compra = "";
		while (st.hasMoreTokens() && contador <= orden) {
			if (contador == orden - 1) {
				compra = st.nextToken().toString().trim();
			}
			contador++;
			st.nextToken();
		}
		return compra;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getConsultaEmpresasAsociadasPorNif(com.bbva.kyfb.kyfbdto.firmas.bo.ConsultaEmpresaAsociadasNifDto)
	 */
	@Override
	public final EmpresaNifOutDto getConsultaEmpresasAsociadasPorNif(
			final ConsultaEmpresaAsociadasNifDto consultaEmpresaAsociadasNifDto)
					throws ExcepcionEjecucionAplicacion {
		return servicioFirmasBoHostUtil
				.getConsultaEmpresasAsociadasPorNif(consultaEmpresaAsociadasNifDto);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#getConsultaEmpresasAsociadasPorReferencia(com.bbva.kyfb.kyfbdto.firmas.bo.ConsultaEmpresaAsociadasRefDto)
	 */
	@Override
	public final EmpresaRefOutDto getConsultaEmpresasAsociadasPorReferencia(
			final ConsultaEmpresaAsociadasRefDto consultaEmpresaAsociadasRefDto)
					throws ExcepcionEjecucionAplicacion {
		return servicioFirmasBoHostUtil
				.getConsultaEmpresasAsociadasPorReferencia(consultaEmpresaAsociadasRefDto);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#deleteComponentePendientes(java.util.List,
	 *      com.bbva.kyfb.kyfbdto.firmas.bo.DatosPAU, java.lang.String,
	 *      java.lang.String)
	 */
	@Override
	public final List<DeletedFilesDto> deleteComponentePendientes(
			final List<FilesDeleteInfo> files, final DatosPAU usuario, final String tipoFirma,
			final String nif, final String codigoAplicacion)
					throws ExcepcionEjecucionAplicacion {

		// List<Object[]> listaObjetos =
		// servicioFirmasDao.findValidacion(usuario
		// .getsTipoValidacion());

		List<DeletedFilesDto> deletedFilesDtos = null;

		// if (listaObjetos != null) {
		try {

			deletedFilesDtos = new ArrayList<DeletedFilesDto>();
			DeletedFilesDto deletedFilesDto = null;
			final String codClienteCash = usuario.getsCanal()
					+ usuario.getsBancoInt() + usuario.getsReferencia();

			final String resultadoAutent = srvAutenticadorPAU.autenticarPAU(usuario);
			if (ConstantesPAU.AUT_OK.equals(resultadoAutent)) {
				final FiltroFicheros filtroFichero = new FiltroFicheros();
				final String[] claseOrd = new String[1];
				for (final FilesDeleteInfo file : files) {
					deletedFilesDto = new DeletedFilesDto();
					claseOrd[0] = file.getsTipoOrden();
					filtroFichero.setClaseOrden(claseOrd);
					filtroFichero.setIdOrden(file.getsIdOrden());
					deletedFilesDto.setOrdenFirmas(file.getsIdOrden());
					deletedFilesDto.setTipoOrden(file.getsTipoOrden());
					FicheroPdteFirma ficheroBorrado;
					try {
						final List<Object[]> componentes = servicioFirmasDao
								.findComponentesPdteReferencia(codClienteCash,
										codigoAplicacion, filtroFichero, false);
						if (componentes != null && componentes.size() >= 1) {
							final List<FicheroPdteFirma> ficherosPendientesFirma = ResulSetDtoConverter
									.createFicherosPdteDtoFromEntity(componentes);
							ficheroBorrado = ficherosPendientesFirma.get(0);
							servicioFirmasBoHostUtil
							.deleteComponentePendienteHost(usuario,
									nif, ficheroBorrado, tipoFirma);
							servicioFirmasDao.updatePesoEstadoFirma(
									UtilFO.EST_ELIMINADO_USUARIO,
									ficheroBorrado.getlPesoActual(),
									codClienteCash, file.getsTipoOrden(),
									file.getsIdOrden());
							servicioFirmasDao.updateEstadoFichero(UtilFO
									.getCodNumero(UtilFO.EST_ELIMINADO_USUARIO),
									codClienteCash, file.getsTipoOrden(), file
									.getsIdOrden());

							//TODO: online o fichero
							if(ConstantesFO.SIGLAS_FIRMA_HOST.equalsIgnoreCase(tipoFirma)){
								servicioFirmasDao.deleteFirmantesFRF(nif, ficheroBorrado.getdFechaCreacion());
							}
							else {
								servicioFirmasDao.deleteFirmantes(
										ficheroBorrado.getNumItem(),
										ficheroBorrado.getdFechaCreacion());
							}

							final Ttlsbfua tlsbfua = ResulSetDtoConverter
									.crearFuaFromDtoDelete(file, usuario);
							servicioFirmasDao.insertAuditoria(tlsbfua);
							deletedFilesDto
							.setCodError(String
									.valueOf(Errores_kyfb_servicios.ELIMINAR_OK));
							if (!ConstantesFO.ORDEN_ONLINE
									.equalsIgnoreCase(ficheroBorrado
											.getModoOrden())) {
								servicioFirmasDao.updateBitDelete(
										usuario.getsCanal(),
										usuario.getsBancoInt(),
										usuario.getsReferencia(),
										new BigDecimal(ficheroBorrado
												.getNumItem()));
							}
						} else {
							deletedFilesDto
							.setCodError(String
									.valueOf(Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE));
						}
					} catch (final ExcepcionEjecucionAplicacion e) {
						final CodigoError ce;
						if (e.getCodigoError().toString()
								.equals(Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR
										.toString())){
							ce = Errores_kyfb_servicios.NO_EXISTE_LA_ORDEN_O_SU_ESTADO_NO_PERMITE_ELIMINARLA;
						} else {
							ce = e.getCodigoError();
						}
						deletedFilesDto.setCodError(String.valueOf(ce));
					}
					deletedFilesDtos.add(deletedFilesDto);
				}
			}

		} catch (final ExcepcionEjecucionAplicacion daoExcepcion) {
			LOG.info(daoExcepcion, "deleteComponentePendientes");
		}
		// }
		return deletedFilesDtos;
	}

//	@Resource(name="servicioEjecucionHttpHTTPClient")
	ExecuteServiceV01 executeServiceV01;
	
	/**
	 * {@inheritDoc}
	 * 
	 * @see com.bbva.kyfb.kyfbbofi.IFirmasBo#putFirmaComponente(com.bbva.kyfb.kyfbdto.firmas.bo.FirmaComponente)
	 */
	@Override
	public final SignedComponentsResponse putFirmaComponente(
			final FirmaComponente firmaComponente)
					throws ExcepcionEjecucionAplicacion {

		SignedComponentsResponse errores = null;
		final DatosPAU datosPau = firmaComponente.getDatosPAU();

		final StringBuilder logSb = new StringBuilder("ValidadorPauImpl --- validacionesToken (parametros)")
		.append(", canal: ").append(datosPau.getsCanal())
		.append(", bancoInterno: ").append(datosPau.getsBancoInt())
		.append(", referencia: ").append(datosPau.getsReferencia())
		.append(", bancoProducto: ").append(datosPau.getsBancoProducto())
		.append(", producto: ").append(datosPau.getsProductoServicio())
		.append(", subproducto: ").append(datosPau.getsCodSubProducto())
		.append(", codUsuario: ").append(datosPau.getsCodUsuario());
		LOG.info(logSb.toString());
		final String codClienteCash = new StringBuilder(datosPau.getsCanal()).append(datosPau.getsBancoInt()).append(datosPau.getsReferencia()).toString();
		// Obtenemos todos los objetos firmables segun la aplicacion
		final List<ObjetoFirmable> listaObjetoFirmable = ResulSetDtoConverter
				.createObjetosFirmablesDtoFromEntity(
						servicioFirmasDao.findObjetosFirmablesPorAplicacion(
								firmaComponente.getsCodOrigen()));
		// Comprobamos que el PAU nos devuelve que podemos firmar
		if (srvAutenticadorPAU.autenticarPAU(firmaComponente.getDatosPAU())
				.equals(ConstantesPAU.AUT_OK)) {
			Boolean hayAuditores = null;
			FicheroInfo file;
			List<UsuarioEmpresaDTO> lisAuditores;
			List<String> listaDisclaimer = new ArrayList<String>();
			// Recorremos todos los ficheros que nos envian
			for (final ComponentePutFirma cf : firmaComponente .getComponentesFirmables()) {
				List<FicheroPdteFirma> resultado = null;
				// Se comprueba que la orden es firmable
				if (buscarObjFirmable(listaObjetoFirmable, cf.getsTipoOrden(),null).isFirmable()) {
					final FiltroFicheros filtro = new FiltroFicheros();
					filtro.setIdOrden(cf.getsIdOrdenFirmas());
					filtro.setClaseOrden(new String[]{cf.getsTipoOrden().toString()});
					try {
						resultado = ResulSetDtoConverter.createFicherosPdteDtoFromEntity(
								servicioFirmasDao.findComponentesPdteReferencia(
										codClienteCash,firmaComponente.getsCodOrigen(),filtro, false));
					} catch (final ExcepcionEjecucionAplicacion e) {
						if (UtilFO.eqError(e,Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR)) {
							errores = servicioFirmasBoUtil.actualizarError(errores,
									Errores_kyfb_servicios.ORDEN_SIN_FIRMA_O_INEXISTENTE.toString(),
									cf.getsIdOrdenFirmas(), cf.getsTipoOrden(), null,null, null);
						} else if (UtilFO.eqError(e,Errores_kyfb_servicios.ERROR_BBDD)) {
							errores = servicioFirmasBoUtil.actualizarError(
									errores, Errores_kyfb_servicios.ERROR_BBDD.toString(),
									cf.getsIdOrdenFirmas(), cf.getsTipoOrden(),
									null, null, null);
						}
					}
					// Se comprueba que no sea nulo o que devuelva al menos
					// un resultado
					if (resultado != null && !resultado.isEmpty()) {
						// Buscamos que no se haya firmado ya en la ffs
						final Ttlsbffs ffsBck = Ttlsbffs.findTtlsbffs(new TtlsbffsPK(
								java.math.BigDecimal.valueOf(resultado.get(0).getsNumItem()),
								resultado.get(0).getdFechaCreacion(),
								firmaComponente.getDatosPAU().getsCodUsuario()));
						// Si no se ha firmado seguimos el procedimiento
						if( ffsBck == null || !ffsBck.getXsnFirmado().equals(UtilFO.XSN_FIRMADO) ) {
							// Llamamos a FDS para preguntar si podemos realizar la firma
							if( servicioFirmasBoUtil.lanzarFDS(buscarObjFirmable(listaObjetoFirmable, cf.getsTipoOrden(),null),
									resultado.get(0), firmaComponente) ) {
								/* Una vez comprobado que la orden es firmable y que existe
								 * procederemos a comprobar si se debe guardar en la ONT
								 * y a realizarlo en caso afirmativo.
								 */
								listaDisclaimer = servicioFirmasBoUtil.comprobarActualizarDisclaimers(
										listaDisclaimer,
										datosPau,
										cf );
								// Incrementamos el peso
								final FicheroPdteFirma fchPdtFirma = resultado.get(0);
								fchPdtFirma.setlPesoActual(
										incrementarPeso(fchPdtFirma
												.getlPesoActual(), cf
												.getsPoderFirma()));
								// Preguntamos si hay auditores para la empresa
								// solo en el caso de que la firma se haya
								// completado
								if (hayAuditores == null
										&& fchPdtFirma.getlPesoActual()
										.compareTo(fchPdtFirma.getlPesoFichero()) == 0) {
									file = new FicheroInfo();
									file.setCodClienteCash(codClienteCash);
									file.setsBancoProducto(firmaComponente
											.getDatosPAU().getsBancoProducto());
									file.setsCodSubproducto(firmaComponente
											.getDatosPAU().getsCodSubProducto());
									file.setsCodProducto(firmaComponente.getDatosPAU()
											.getsProductoServicio());
									lisAuditores = servicioFirmasBoClientsUtil
											.getAuditoresReferencia(resultado.get(0), file, file.getCodClienteCash());
									hayAuditores = !CollectionUtils.isEmpty(lisAuditores);
									hayAuditores = false;
								} else {
									file = null;
									lisAuditores = null;
								}
								// Aqui recuperamos los objetos CAB, SFO,
								// FFS para dejarlo como estuviera
								// en caso de error
								// ***********************************
								// Hacemos backup de la SFO
								final Ttlsbsfo sfoBck = Ttlsbsfo.findTtlsbsfo(new TtlsbsfoPK(
										java.math.BigDecimal.valueOf(fchPdtFirma
												.getsNumItem()),
												cf.getsIdOrdenFirmas(), cf.getsTipoOrden()
												.toString(), codClienteCash));
								// Actualizamos el estado
								fchPdtFirma.setsCodEstadoFichero(
										actualizarEstado(
												fchPdtFirma.getlPesoActual(),
												firmaComponente.getsTipoFirmante()
												.equalsIgnoreCase(
														UtilFO.USUARIO_AUDITOR),
														hayAuditores == null ? false
																: hayAuditores));
								boolean continuar = true;
								try {
									// Se actualizan las tablas
									// CAB(updateEstadoFichero)
									// SFO(updatePesoEstadoFirma) y
									// FFS(insertFirmante)
									// y la auditoria FUA (insertAuditoriaFirma)
									servicioFirmasBoUtil.actualizarPutFirmaComponente(
											codClienteCash, fchPdtFirma,
											firmaComponente, cf, UtilFO.XSN_FIRMADO);
								} catch (final Exception e) {
									LOG.error("ServicioFirmasBoImpl.putFirmaComponente - No se ha podido actualizar en las tablas ");
									errores = servicioFirmasBoUtil
											.actualizarError(
													errores,
													Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE
													.toString(), cf
													.getsIdOrdenFirmas(), cf
													.getsTipoOrden(), null,
													null, null);
									// Se hace marcha atras
									servicioFirmasBoUtil.marchaAtras(sfoBck, codClienteCash, resultado.get(0),
											firmaComponente, cf);
									continuar = false;
								}
								if (continuar) {
									// Si el estado es pendiente de auditor se lanza
									// el asistente
									if (fchPdtFirma.getsCodEstadoFichero()
											.equalsIgnoreCase(UtilFO.EST_PDTE_AUDITOR)) {

										// lanzar asistentes con la url del campo
										// DES_URLAUD
										InfoAssistantDto respuestaAsistente = new InfoAssistantDto();
										try {
											//									respuestaAsistente = servicioFirmasBoAsistenteUtil
											//											.lanzarAsistentePut(
											//													buscarObjFirmable(
											//															listaObjetoFirmable,
											//															cf.getsTipoOrden(),
											//															null)
											//															.getsDesUrlAud(),
											//													fchPdtFirma,
											//													firmaComponente,
											//													cf,
											//													Constantes.SIGLAS_FIRMA_SERVIDOR);

											respuestaAsistente = (InfoAssistantDto) servicioFirmasBoAsistenteUtil.respuestaAsistenteToDto(
													"com.bbva.kyfb.kyfbdto.firmas.bo.InfoAssistantDto",
													new StringBuilder("<infoAssistantDto>")
													.append("<codError>ASI0100000</codError>")
													.append("<codErrorTx></codErrorTx>")
													.append("<descError></descError>")
													.append("<observaciones></observaciones>")
													.append("</infoAssistantDto>").toString());
											if (UtilFO.ASISTENTE_OK
													.equalsIgnoreCase(respuestaAsistente.getCodError())) {
												// ha ido bien
												errores = servicioFirmasBoUtil
														.actualizarError(
																errores,
																Errores_kyfb_servicios.ORDEN_PENDIENTE_DE_AUDITAR
																.toString(),
																cf.getsIdOrdenFirmas(),
																cf.getsTipoOrden(),
																respuestaAsistente
																.getCodErrorTx(),
																respuestaAsistente
																.getDescError(),
																respuestaAsistente
																.getObservaciones());

												servicioFirmasBoUtil
												.insertarFirmanteAuditoria(
														codClienteCash,
														fchPdtFirma,
														firmaComponente, cf,
														(short) 4);
												//TODO quitar este codigo
												// Se lanzan las alertas y las notificaciones
												lanzarAlertasYNotificaciones(resultado.get(0), file, lisAuditores, datosPau);
											} else {
												// Si el assitente ha devuelto un
												// codigo de error
												errores = servicioFirmasBoUtil
														.actualizarError(
																errores,
																Errores_kyfb_servicios.ERROR_AL_LANZAR_ASISTENTE
																.toString(),
																cf.getsIdOrdenFirmas(),
																cf.getsTipoOrden(),
																respuestaAsistente
																.getCodErrorTx(),
																respuestaAsistente
																.getDescError(),
																respuestaAsistente
																.getObservaciones());
												// Se hace marcha atras
												servicioFirmasBoUtil.marchaAtras(sfoBck, codClienteCash, resultado.get(0),
														firmaComponente, cf);
											}
										} catch (final Exception e) {
											LOG.error("ServicioFirmasBoImpl.putFirmaComponente - El asistente del auditor ha ido mal ");
											errores = servicioFirmasBoUtil
													.actualizarError(
															errores,
															Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE
															.toString(),
															cf.getsIdOrdenFirmas(), cf
															.getsTipoOrden(),
															respuestaAsistente
															.getCodErrorTx(),
															respuestaAsistente
															.getDescError(),
															respuestaAsistente
															.getObservaciones());
											// Se hace marcha atras
											servicioFirmasBoUtil.marchaAtras(sfoBck, codClienteCash, resultado.get(0),
													firmaComponente, cf);
										}
										// Si el estado es pendiente de ejecucion,
										// es que se ha auditado bien y
										// se tiene que lanzar el asistente y
										// actualizar el estado a enviado
									} else if (fchPdtFirma.getsCodEstadoFichero()
											.equalsIgnoreCase(UtilFO.EST_ENV_ASISTENTE)) {
										// lanzar asistentes con la url del campo
										// DES_URLEJE
										InfoAssistantDto respuestaAsistente = new InfoAssistantDto();
										ObjetoFirmable obj = new ObjetoFirmable();
										obj = buscarObjFirmable(
												listaObjetoFirmable,
												cf.getsTipoOrden(),
												null);
										
//										else{
											try {
												//TODO: lanzamos servicio REST de fichero.
												if(obj.getsDesUrlEje().indexOf(ConstantesFO.ES_FICHERO)!=-1){
													FicheroRequest ficheroRequest = new FicheroRequest();
													
													ficheroRequest.setCanal(firmaComponente.getDatosPAU().getsCanal());
													ficheroRequest.setBancoInterno(firmaComponente.getDatosPAU().getsBancoInt()); 
													ficheroRequest.setBancoProducto(firmaComponente.getDatosPAU().getsBancoProducto());
													ficheroRequest.setAplicacion(firmaComponente.getsCodOrigen());
													ficheroRequest.setIdOrden(cf.getsIdOrdenFirmas());
													ficheroRequest.setNumItem(String.valueOf(fchPdtFirma.getsNumItem()));
													ficheroRequest.setProducto(firmaComponente.getDatosPAU().getsProductoServicio());
													ficheroRequest.setReferencia(firmaComponente.getDatosPAU().getsReferencia());
													ficheroRequest.setSubproducto(firmaComponente.getDatosPAU().getsCodSubProducto());
													ficheroRequest.setTipoFirma(cf.getsPoderFirma());
													ficheroRequest.setTipoOrden(cf.getsTipoOrden());
													
													respuestaAsistente = executeServiceV01.executeFile(ficheroRequest);
												}
												else{
												respuestaAsistente = servicioFirmasBoAsistenteUtil
														.lanzarAsistentePut(
																		obj.getsDesUrlEje(),
																		fchPdtFirma,
																		firmaComponente,
																		cf,
																		ConstantesFO.SIGLAS_FIRMA_SERVIDOR);
												}
												
												if (respuestaAsistente
														.getCodError()
														.equalsIgnoreCase(UtilFO.ASISTENTE_OK)) {
													// Actualizamos el estado del
													// fichero a
													// firmado y enviado HO
													fchPdtFirma.setsCodEstadoFichero(
															UtilFO.EST_FIRMADO_ENVIADO);
													servicioFirmasBoUtil
													.actualizarPutFirmaComponente(
															codClienteCash,
															fchPdtFirma,
															firmaComponente, cf, UtilFO.XSN_FIRMADO);
													if (firmaComponente.getsTipoFirmante()
															.equalsIgnoreCase(
																	UtilFO.USUARIO_AUDITOR)) {
														servicioFirmasBoUtil
														.insertarFirmanteAuditoria(
																codClienteCash,
																fchPdtFirma,
																firmaComponente,
																cf, (short) 9);
													} else {
														servicioFirmasBoUtil
														.insertarFirmanteAuditoria(
																codClienteCash,
																fchPdtFirma,
																firmaComponente,
																cf, (short) 4);
													}
	
													errores = servicioFirmasBoUtil
															.actualizarError(
																	errores,
																	Errores_kyfb_servicios.ORDEN_FIRMADA_Y_EJECUTADA
																	.toString(),
																	cf.getsIdOrdenFirmas(),
																	cf.getsTipoOrden(),
																	respuestaAsistente
																	.getCodErrorTx(),
																	respuestaAsistente
																	.getDescError(),
																	respuestaAsistente
																	.getObservaciones());
												} else {
													errores = servicioFirmasBoUtil
															.actualizarError(
																	errores,
																	Errores_kyfb_servicios.ERROR_AL_LANZAR_ASISTENTE
																	.toString(),
																	cf.getsIdOrdenFirmas(),
																	cf.getsTipoOrden(),
																	respuestaAsistente
																	.getCodErrorTx(),
																	respuestaAsistente
																	.getDescError(),
																	respuestaAsistente
																	.getObservaciones());
													// Se hace marcha atras
													servicioFirmasBoUtil.marchaAtras(sfoBck, codClienteCash, resultado.get(0),
															firmaComponente, cf);
												}
											} catch (final Exception e) {
												LOG.error("ServicioFirmasBoImpl.putFirmaComponente - El asistente del pendiente de ejecutar ha ido mal ");
												errores = servicioFirmasBoUtil
														.actualizarError(
																errores,
																Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE
																.toString(),
																cf.getsIdOrdenFirmas(), cf
																.getsTipoOrden(),
																respuestaAsistente
																.getCodErrorTx(),
																respuestaAsistente
																.getDescError(),
																respuestaAsistente
																.getObservaciones());
												// Se hace marcha atras
												servicioFirmasBoUtil.marchaAtras(sfoBck, codClienteCash, resultado.get(0),
														firmaComponente, cf);
											}
//										}
										// Si la orden queda pendiente de mas firmas
										// se actualiza los errores para la
										// devolucion
									} else if (fchPdtFirma.getsCodEstadoFichero()
											.equalsIgnoreCase(UtilFO.EST_FDO_PARCIAL)) {
										errores = servicioFirmasBoUtil
												.actualizarError(
														errores,
														Errores_kyfb_servicios.ORDEN_FIRMADA_PARCIALMENTE
														.toString(), cf
														.getsIdOrdenFirmas(),
														cf.getsTipoOrden(), null, null,
														null);
										servicioFirmasBoUtil.insertarFirmanteAuditoria(
												codClienteCash, fchPdtFirma,
												firmaComponente, cf, (short) 4);
									}
								}
							}
						}else {
							// De lo contrario quiere decirse que se ha firmado y
							//hay que devolver al usuario el error
							LOG.error("ServicioFirmasBoImpl.putFirmaComponente - La orden ".concat(
									cf.getsIdOrdenFirmas()).concat(" ya se ha firmado para este usuario: ").concat(
											firmaComponente.getDatosPAU().getsCodUsuario()));
							errores = servicioFirmasBoUtil
									.actualizarError(
											errores,
											Errores_kyfb_servicios.ORDEN_YA_FIRMADA_POR_EL_USUARIO
											.toString(), cf
											.getsIdOrdenFirmas(),
											cf.getsTipoOrden(), null, null,
											null);

						}
					}
				} else {
					// No es firmable asi que se guarda el error y se pasa
					// al siguiente fichero
					LOG.error("ServicioFirmasBoImpl.putFirmaComponente - La orden "
							+ cf.getsTipoOrden() + " no es firmable: ");
					errores = servicioFirmasBoUtil
							.actualizarError(
									errores,
									Errores_kyfb_servicios.ORDEN_NO_FIRMABLE_POR_LA_APLICACION_INVOCADORA
									.toString(),
									cf.getsIdOrdenFirmas(), cf.getsTipoOrden(),
									null, null, null);
				}
			}
		}
		return errores;
	}

	private void lanzarAlertasYNotificaciones(final FicheroPdteFirma ficheroPdteFirma,
			final FicheroInfo file, final List<UsuarioEmpresaDTO> lisAuditores, final DatosPAU datosPau) {
		// Se lanzan las alertas por correo electronico para
		//avisar a los auditores de la empresa que puedan firmar
		try {
			servicioFirmasBoUtil.lanzarAlertasPNM(ficheroPdteFirma, file, lisAuditores);
		}catch(final Exception e) {
			LOG.error("Error en lanzarAlertasPNM ".concat(e.getMessage()));
		}
		// Se lanzan las notificaciones para recibir por el movil
		try {
			servicioFirmasBoUtil.lanzarNotificaciones(datosPau);
		}catch(final Exception e) {
			LOG.error("Error en lanzarNotificaciones ".concat(e.getMessage()));
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final SignedComponentsResponse putFirmaComponenteHost(
			final FirmaComponente firmaComponente)
					throws ExcepcionEjecucionAplicacion, PropiedadNoEncontradaExcepcion {
		// Se comprueba que el DNI no sea ni nulo ni vacio
		final Object[] obligatorios = new Object[] { firmaComponente.getsNIFUsuario() };
		ValidationUtils.validarObligatorios(obligatorios,
				Errores_kyfb_servicios.CAMPO_OBLIGATORIO_NO_INFORMADO, true);
		// listaDisclaimer - Guardara la lista de disclaimers que se van insertando
		List<String> listaDisclaimer = new ArrayList<String>();
		SignedComponentsResponse errores = null;
		// Obtenemos todos los objetos firmables segun la aplicacion
		final List<ObjetoFirmable> listaObjetoFirmable = ResulSetDtoConverter.createObjetosFirmablesDtoFromEntity(
				servicioFirmasDao.findObjetosFirmablesPorAplicacion(firmaComponente.getsCodOrigen()));

		// Comprobamos que el PAU nos devuelve que podemos firmar
		if (srvAutenticadorPAU.autenticarPAU(firmaComponente.getDatosPAU())
				.equals(ConstantesPAU.AUT_OK)) {
			// Recorremos todos los ficheros que nos envian
			ObjetoFirmable objetoFirmable;

			final String codClienteCash = firmaComponente.getDatosPAU().getsCanal()
					+ firmaComponente.getDatosPAU().getsBancoInt()
					+ firmaComponente.getDatosPAU().getsReferencia();

			for (final ComponentePutFirma cf : firmaComponente.getComponentesFirmables()) {
				objetoFirmable = buscarObjFirmable(listaObjetoFirmable,cf.getsTipoOrden(), null);
				// Se comprueba que la orden es firmable
				if (objetoFirmable.isFirmable()) {
					/* Una vez comprobado que la orden es firmable y que existe
					 * procederemos a comprobar si se debe guardar en la ONT
					 * y a realizarlo en caso afirmativo.
					 */
					listaDisclaimer = servicioFirmasBoUtil.comprobarActualizarDisclaimers(
							listaDisclaimer,
							firmaComponente.getDatosPAU(),
							cf );
					errores = firmarObjetoFirmable(firmaComponente, errores,codClienteCash, objetoFirmable, cf);
				} else {
					// No es firmable asi que se guarda el error y se pasa
					// al siguiente fichero
					LOG.error("ServicioFirmasBoImpl.putFirmaComponenteHost - La orden " + cf.getsTipoOrden() + " no es firmable: ");
					errores = servicioFirmasBoUtil.actualizarError(errores,
							Errores_kyfb_servicios.ORDEN_NO_FIRMABLE_POR_LA_APLICACION_INVOCADORA.toString(),
							cf.getsIdOrdenFirmas(), cf.getsTipoOrden(),null, null, null);
				}
			}
		}
		return errores;
	}

	/**
	 * Firmar objeto firmable.
	 * 
	 * @param firmaComponente
	 *            the firma componente
	 * @param errors
	 *            the errors
	 * @param codClienteCash
	 *            the cod cliente cash
	 * @param objetoFirmable
	 *            the objeto firmable
	 * @param cf
	 *            the cf
	 * @return the signed components response
	 * @throws PropiedadNoEncontradaExcepcion
	 *             the propiedad no encontrada excepcion
	 */
	private SignedComponentsResponse firmarObjetoFirmable(
			final FirmaComponente firmaComponente,
			final SignedComponentsResponse errors, final String codClienteCash,
			final ObjetoFirmable objetoFirmable, final ComponentePutFirma cf)
					throws PropiedadNoEncontradaExcepcion {
		SignedComponentsResponse errores;
		final FiltroFicheros filtro = new FiltroFicheros();
		filtro.setIdOrden(cf.getsIdOrdenFirmas());
		filtro.setClaseOrden(new String[] { cf.getsTipoOrden().toString() });

		try {
			final List<FicheroPdteFirma> resultado = ResulSetDtoConverter
					.createFicherosPdteDtoFromEntity(servicioFirmasDao
							.findComponentesPdteReferencia(codClienteCash,
									firmaComponente.getsCodOrigen(), filtro,
									false));
			final FicheroPdteFirma fichero = resultado.get(0);
			final String modoOrden = fichero.getModoOrden().trim();

			// Se comprueba si es orden online o fichero para lanzar una
			// transaccion u otra
			if (modoOrden.equalsIgnoreCase(ConstantesFO.ORDEN_ONLINE)) {
				servicioFirmasBoHostUtil.firmarOrdenOnline(firmaComponente,
						fichero);
			} else {
				servicioFirmasBoHostUtil.firmarFicheroNoOnline(firmaComponente,
						fichero);
			}

			errores = comprobarResultadoFirma(firmaComponente, codClienteCash,
					objetoFirmable, cf, errors, fichero);
		} catch (final ExcepcionEjecucionAplicacion e) {
			final String strErr;
			if (UtilFO.eqError(e,Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR)) {
				strErr = Errores_kyfb_servicios.ORDEN_SIN_FIRMA_O_INEXISTENTE.toString();
			}else{
				strErr = e.getCodigoError().toString();
				LOG.error("Error en el proceso de firmado de la orden " + cf.getsTipoOrden(), e);
			}
			errores = servicioFirmasBoUtil.actualizarError(
					errors, strErr,
					cf.getsIdOrdenFirmas(), cf.getsTipoOrden(), null,null, null);
		}

		return errores;
	}

	/**
	 * Comprobar resultado firma.
	 * 
	 * @param firmaComponente
	 *            the firma componente
	 * @param codClienteCash
	 *            the cod cliente cash
	 * @param objetoFirmable
	 *            the objeto firmable
	 * @param cpf
	 *            the cf
	 * @param errors
	 *            the errors
	 * @param fichero
	 *            the fichero
	 * @return the signed components response
	 * @throws PropiedadNoEncontradaExcepcion
	 *             the propiedad no encontrada excepcion
	 */
	private SignedComponentsResponse comprobarResultadoFirma(
			final FirmaComponente firmaComponente, final String codClienteCash,
			final ObjetoFirmable objetoFirmable, final ComponentePutFirma cpf,
			final SignedComponentsResponse errors,
			final FicheroPdteFirma fichero)
					throws PropiedadNoEncontradaExcepcion {
		final SignedComponentsResponse errores;
		// Si se ha firmado todo correctamente HO
		if (fichero.getsCodEstadoFichero().trim()
				.equalsIgnoreCase(UtilFO.EST_ENV_ASISTENTE)) {
			// Comprobamos si es orden online
			if (fichero.getModoOrden().trim()
					.equalsIgnoreCase(ConstantesFO.ORDEN_ONLINE)) {
				errores = lanzarAsistenteOnline(
						firmaComponente, codClienteCash, objetoFirmable, cpf,
						fichero, errors);
			} else {
				// Si no es orden online
				fichero.setsCodEstadoFichero(
						UtilFO.EST_FIRMADO_ENVIADO);
				servicioFirmasBoHostUtil.actualizarPutFirmaComponenteHost(
						codClienteCash, fichero, firmaComponente, cpf, UtilFO.XSN_FIRMADO);
				errores = servicioFirmasBoUtil.actualizarError(errors,
						Errores_kyfb_servicios.ORDEN_FIRMADA_Y_EJECUTADA
						.toString(), cpf.getsIdOrdenFirmas(), cpf
						.getsTipoOrden(), null, null, null);
				servicioFirmasBoUtil.insertarFirmanteAuditoria(
						codClienteCash,
						fichero,
						firmaComponente,
						cpf, (short) 4);
			}
			// Si la orden queda pendiente de mas firmas se actualiza los
			// errores para la devolucion FP
		} else if (fichero.getsCodEstadoFichero().equalsIgnoreCase(
				UtilFO.EST_FDO_PARCIAL)) {
			fichero.setsCodEstadoFichero(UtilFO.EST_FIRMADO_ENVIADO);
			servicioFirmasBoHostUtil.actualizarPutFirmaComponenteHost(codClienteCash,
					fichero, firmaComponente, cpf, UtilFO.XSN_FIRMADO);
			errores = servicioFirmasBoUtil.actualizarError(errors,
					Errores_kyfb_servicios.ORDEN_FIRMADA_PARCIALMENTE
					.toString(), cpf.getsIdOrdenFirmas(), cpf
					.getsTipoOrden(), null, null, null);
			servicioFirmasBoUtil.insertarFirmanteAuditoria(
					codClienteCash,
					fichero,
					firmaComponente,
					cpf, (short) 4);
		} else {
			errores = errors;
		}
		return errores;
	}

	/**
	 * Lanzar asistente online.
	 *
	 * @param firmaComponente the firma componente
	 * @param codClienteCash the cod cliente cash
	 * @param objetoFirmable the objeto firmable
	 * @param cf the cf
	 * @param fichero the fichero
	 * @param errors the errors
	 * @return the signed components response
	 */
	private SignedComponentsResponse lanzarAsistenteOnline(
			final FirmaComponente firmaComponente, final String codClienteCash,
			final ObjetoFirmable objetoFirmable, final ComponentePutFirma cf,
			final FicheroPdteFirma fichero,
			final SignedComponentsResponse errors) {
		SignedComponentsResponse errores = errors;
		// lanzar asistentes con la url del campo
		// DES_URLEJE
		InfoAssistantDto respuestaAsistente = new InfoAssistantDto();
		//Se realiza la copia de seguridad antes de actualizar la bbdd
		// Aqui recuperamos los objetos CAB, SFO,
		// FFS para dejarlo como estuviera
		// en caso de error
		// ***********************************
		// Hacemos backup de la SFO
		final Ttlsbsfo sfoBck = Ttlsbsfo.findTtlsbsfo(new TtlsbsfoPK(
				java.math.BigDecimal.valueOf(fichero
						.getsNumItem()),
						cf.getsIdOrdenFirmas(), cf.getsTipoOrden()
						.toString(), codClienteCash));
		try {
			// Actualizamos el estado del
			// fichero a
			// lanzado el asistente FF
			servicioFirmasBoHostUtil
			.actualizarPutFirmaComponenteHost(
					codClienteCash,
					fichero,
					firmaComponente, cf, UtilFO.XSN_FIRMADO);
			respuestaAsistente = servicioFirmasBoAsistenteUtil.lanzarAsistentePut(
					objetoFirmable.getsDesUrlEje(), fichero, firmaComponente,
					cf, ConstantesFO.SIGLAS_FIRMA_HOST);
			if (respuestaAsistente.getCodError().equalsIgnoreCase(
					UtilFO.ASISTENTE_OK)) {
				// Actualizamos el estado del fichero a
				// firmado y enviado HO
				fichero.setsCodEstadoFichero(UtilFO.EST_FIRMADO_ENVIADO);
				servicioFirmasBoHostUtil.actualizarPutFirmaComponenteHost(
						codClienteCash, fichero, firmaComponente, cf, UtilFO.XSN_FIRMADO);
				errores = servicioFirmasBoUtil.actualizarError(errores,
						Errores_kyfb_servicios.ORDEN_FIRMADA_Y_EJECUTADA
						.toString(), cf.getsIdOrdenFirmas(), cf
						.getsTipoOrden(), null, null, null);
				servicioFirmasBoUtil.insertarFirmanteAuditoria(
						codClienteCash,
						fichero,
						firmaComponente,
						cf, (short) 4);
			} else {
				errores = servicioFirmasBoUtil.actualizarError(errores,
						Errores_kyfb_servicios.ERROR_AL_LANZAR_ASISTENTE
						.toString(), cf.getsIdOrdenFirmas(), cf
						.getsTipoOrden(), respuestaAsistente
						.getCodErrorTx(), respuestaAsistente
						.getDescError(), respuestaAsistente
						.getObservaciones());

				// Se hace marcha atras en bbdd
				servicioFirmasBoHostUtil.marchaAtrasBBDDHost(sfoBck, codClienteCash, fichero,
						firmaComponente, cf);

				// Se hace marcha atras
				servicioFirmasBoHostUtil.marchaAtrasHost(codClienteCash,
						fichero, firmaComponente);
			}
		} catch (final Exception e) {
			LOG.error("ServicioFirmasBoImpl.putFirmaComponenteHost - El asistente del pendiente de ejecutar ha ido mal ");
			errores = servicioFirmasBoUtil
					.actualizarError(errores,
							Errores_kyfb_servicios.ERROR_AL_LANZAR_ASISTENTE
							.toString(), cf.getsIdOrdenFirmas(), cf
							.getsTipoOrden(), respuestaAsistente
							.getCodErrorTx(), respuestaAsistente
							.getDescError(), respuestaAsistente
							.getObservaciones());

			// Se hace marcha atras en bbdd
			servicioFirmasBoHostUtil.marchaAtrasBBDDHost(sfoBck, codClienteCash, fichero,
					firmaComponente, cf);

			// Se hace marcha atras
			servicioFirmasBoHostUtil.marchaAtrasHost(codClienteCash, fichero,
					firmaComponente);

		}
		return errores;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final List<FirmanteInfo> getUsuariosFirmaPedteHost(final FicheroInfo file, final FicheroPdteFirma ficheroPdte) {
		return servicioFirmasBoHostUtil.getUsuariosFirmaPedteHost(file,ficheroPdte);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final ListNData<FicheroPdteFirma,String[]> getComponentesPendientesReferenciaHost(
			final FicheroInfo file) {
		return servicioFirmasBoHostUtil
				.getComponentesPendientesReferenciaHost(file);
	}


	/**
	 * incrementarPeso Incrementa el peso que se le pasa segun el poder de firma
	 * que igualmente se le pasa.
	 * 
	 * @param peso
	 *            the peso
	 * @param poderFirma
	 *            the poder firma
	 * @return the double
	 * @throws ExcepcionEjecucionAplicacion
	 *             the excepcion ejecucion aplicacion
	 */
	private double incrementarPeso(final double peso, final String poderFirma)
			throws ExcepcionEjecucionAplicacion {
		BigDecimal pesoFinal = BigDecimal.valueOf(peso);

		if (StringUtils.isBlank(poderFirma)
				|| poderFirma.equalsIgnoreCase(UtilFO.FIRMA_SOLIDARIO)) {
			pesoFinal = pesoFinal.add(BigDecimal.valueOf(UtilFO.PODER_FIRMA_SOLIDARIO));
		} else if (poderFirma.equalsIgnoreCase(UtilFO.FIRMA_MANCOMUNADO2)) {
			pesoFinal = pesoFinal.add(BigDecimal.valueOf(UtilFO.PODER_FIRMA_MANCOMUNADO2));
		} else if (poderFirma.equalsIgnoreCase(UtilFO.FIRMA_MANCOMUNADO3)) {
			pesoFinal = pesoFinal.add(BigDecimal.valueOf(UtilFO.PODER_FIRMA_MANCOMUNADO3));
		} else if (poderFirma.equalsIgnoreCase(UtilFO.FIRMA_MANCOMUNADO4)) {
			pesoFinal = pesoFinal.add(BigDecimal.valueOf(UtilFO.PODER_FIRMA_MANCOMUNADO4));
		}

		// Si el resultado es mayor que lo que puede firmar el solidario
		// entoces se devuelve lo del solidario
		if (pesoFinal.compareTo(BigDecimal.valueOf(UtilFO.PODER_FIRMA_SOLIDARIO)) == 1) {
			pesoFinal = BigDecimal.valueOf(UtilFO.PODER_FIRMA_SOLIDARIO);
		}
		return pesoFinal.doubleValue();
	}

	/**
	 * Buscar obj firmable.
	 * 
	 * @param lstObjFir
	 *            the lst obj fir
	 * @param cod
	 *            the cod
	 * @param pais
	 *            the pais
	 * @return the objeto firmable
	 * @throws ExcepcionEjecucionAplicacion
	 *             the excepcion ejecucion aplicacion
	 */
	private ObjetoFirmable buscarObjFirmable(
			final List<ObjetoFirmable> lstObjFir, final String cod,
			final String pais) throws ExcepcionEjecucionAplicacion {
		final boolean hayPais = StringUtils.isNotBlank(pais);
		boolean codObjEquals;
		boolean paisEquals;

		for (final ObjetoFirmable obj : lstObjFir) {
			codObjEquals = obj.getsCodObj().trim().equals(cod.trim());
			paisEquals = obj.getsPais().trim()
					.equalsIgnoreCase(StringUtils.trim(pais));

			if (codObjEquals && (!hayPais || paisEquals)) {
				return obj;
			}
		}
		LOG.error("ServicioFirmasBoImpl.buscarObjFirmable - No hay ningun objeto coincidente ");
		throw new ExcepcionEjecucionAplicacion(
				Errores_kyfb_servicios.NO_EXISTEN_DATOS_A_LISTAR);
	}

	/**
	 * actualizarEstado Devuelve el estado acutalizado segun el peso, de si es
	 * apoderado, y si hay auditores en la empresa o no.
	 * 
	 * @param peso
	 *            the peso
	 * @param esApoderado
	 *            the es apoderado
	 * @param hayAuditores
	 *            the hay auditores
	 * @return the string
	 */
	private String actualizarEstado(final double peso,
			final boolean esApoderado, final boolean hayAuditores) {
		final String estado;
		if (peso < 1) {
			estado = UtilFO.EST_FDO_PARCIAL;// FP

			/*
			 * Si el peso es mayor que uno el fichero esta firmado por los
			 * apoderados y pasamos a comprobar si hay auditores y si ha firmado
			 * alguno de ellos.
			 */
		} else if (!esApoderado && hayAuditores) {
			// Si el usuario es un apoderado y hay auditores en la empresa,
			// pasamos a estado de
			// pendiente de firma de un auditor
			estado = UtilFO.EST_PDTE_AUDITOR;// PA
		} else {
			// Si el usuario es auditor pasamos a estado de pendiente por el asistente
			estado = UtilFO.EST_ENV_ASISTENTE;// FF
		}
		return estado;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.bbva.kyfb.kyfbbofi.IFirmasBo#getDetalleComponente(com.bbva.kyfb.kyfbdto
	 * .firmas.bo.InfoComponentInDto)
	 */
	@Override
	public final InfoComponentDetailDto getDetalleComponente(final InfoComponentInDto info)
			throws ExcepcionEjecucionAplicacion {
		// OperacionCBTFServlet?proceso=TLBHPrDetalleFicheroSpring&operacion=TLBHOpDetalleFicheroSpring&accion=detalleFicheroSpring&idOrigenSpring=hca9sv93&claseOrdenSpring=TRA&idiomaSpring=CAS&mostrarOrdenes=S

		String urlDetalleComp;

		try {
			LOG.info("SE HACE LA CONSULTA A BBDD con APP="
					+ info.getsCodOrigen());
			final List<ObjetoFirmable> listaObjetoFirmable = ResulSetDtoConverter
					.createObjetosFirmablesDtoFromEntity(servicioFirmasDao
							.findObjetosFirmablesPorAplicacion(info
									.getsCodOrigen()));
			LOG.info("SE HA REALIZADO LA CONSULTA CORRECTAMENTE, SE CONSULTA OBJ FIRMABLE con TIPOORDEN="
					+ info.getsCodTipoOrden());
			final ObjetoFirmable objFir = buscarObjFirmable(listaObjetoFirmable,
					info.getsCodTipoOrden(), null);
			LOG.info("SE HA REALIZADO LA CONSULTA DE OBJ FIRMABLE CORRECTAMENTE");

			urlDetalleComp = StringUtils.trim(objFir.getsDesUrlDet());
			LOG.info("LA URL BASE QUE SE LANZARA PARA ASISTENTE ES: "
					+ urlDetalleComp);

		} catch (final ExcepcionEjecucionAplicacion e) {
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfb_servicios.ERROR_GENERICO_EN_LA_REALIZACION_DEL_DETALLE,
					e);
		}

		InfoComponentDetailDto infoCompDetDto;
		boolean mockTest = false;

		// Se recoge la propiedad para saber si es mock o no
		try {
			mockTest = ArqSpringContext
					.getPropiedadBoolean(ConstantesFO.CBTFTEST);
		} catch (final PropiedadNoEncontradaExcepcion e1) {
			LOG.error("ServicioFirmasBoImpl.getDetalleComponente - La propiedad "
					+ ConstantesFO.CBTFTEST + " no existe");
		} catch (final PropiedadNoParseableExcepcion e1) {
			LOG.error("ServicioFirmasBoImpl.getDetalleComponente - La propiedad "
					+ ConstantesFO.CBTFTEST + " no es parseable");
		}

		if (mockTest) {
			infoCompDetDto = servicioFirmasBoAsistenteUtil
					.lanzarAsistenteDetalleMock(info.getsIdOrdenFirmas()
							+ info.getsCodTipoOrden()
							+ info.getsMostrarOrdenes()); // Nombre de los xml's
			// de prueba:
			// hl51r123TRP.xml
		} else {
			infoCompDetDto = servicioFirmasBoAsistenteUtil
					.lanzarAsistenteDetalle(urlDetalleComp, info);
		}

		return infoCompDetDto;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.bbva.kyfb.kyfbbofi.IFirmasBo#updateNumeroAleatorioComponentesUsuario(com.bbva.kyfb.kyfbdto
	 * .firmas.bo.UpdateInfoInDto)
	 */
	@Override
	public final UpdateInfoOutDto updateNumeroAleatorioComponentesUsuario(final UpdateInfoInDto info) throws ExcepcionEjecucionAplicacion {

		final UpdateInfoOutDto respuesta = new UpdateInfoOutDto();
		// Generamos un nuevo numero aleatorio
		final String nuevoNumAleatorio = Long.toString(FuncionesPAU.getReferenciaNPosiciones(UtilFO.LONGITUD_NUM_ALEATORIO));

		// Recorremos los IdOrden
		for (final InfoOrdenInDto idOrden : info.getInfoOrdenes()) {
			LOG.info("ServicioFirmasBoImpl.updateNumeroAleatorioComponentesUsuario - Procesamos el idOrden: "+idOrden);
			final FiltroFicheros filtro = new FiltroFicheros();
			filtro.setIdOrden(idOrden.getsIdOrdenFirmas());
			// Vamos a obtener los ficheros (numItem, Timfichero, ...) filtrando por idOrden
			final List<FicheroPdteFirma> resultado = ResulSetDtoConverter
					.createFicherosPdteDtoFromEntity(
							servicioFirmasDao.findComponentesPdteReferencia(
									info.getsCanal()+info.getsBancoInt()+info.getsReferencia(),
									info.getsCodigoAplicacion(), filtro, false));
			LOG.info("ServicioFirmasBoImpl.updateNumeroAleatorioComponentesUsuario - Obtenemos ficheros: "+resultado.size());
			for (final FicheroPdteFirma fichero : resultado) {
				fichero.setsNumeroAleatorio(nuevoNumAleatorio);
				if (info.getsTipoFirma().equalsIgnoreCase(ConstantesFO.SIGLAS_FIRMA_SERVIDOR)) {
					// Firma Servidor
					// Para cada fichero, realizamos el insert/update del numero aleatorio
					servicioFirmasBoUtil.insertarActualizarNumeroAleatorio(fichero, info, idOrden.getsPoderFirma());
				} else {
					// Firma Host
					servicioFirmasBoHostUtil.insertarActualizarNumeroAleatorio(fichero, info);
				}
			}
		}
		// Devolvemos el numero aleatorio generado e insertado
		respuesta.setsNumeroAleatorio(nuevoNumAleatorio);
		return respuesta;
	}

	@Override
	public String mergeMsgAcepTipoOrden(final String codAplicacion, final String codTipoOrden, final List<FirmanteInfo> listaFirmantes) throws ExcepcionEjecucionAplicacion{

		final Set<String> setCodNameFrmts = new HashSet<String>(8);
		for(final FirmanteInfo firNfo:listaFirmantes){ //Para eliminar los duplicados.
			setCodNameFrmts.add(firNfo.getCodUsuario());
		}
		// Verificamos si esta en la tabla ont y que valores tiene en la tabla ppa
		final String[] arrMsg = servicioFirmasDao.findMensajeAceptacion(codAplicacion, new String[]{codTipoOrden}).get(0);
		final List<String> lstCodUsu = servicioFirmasDao.findCodUsuFirmaPrevia(codTipoOrden, setCodNameFrmts.toArray(new String[setCodNameFrmts.size()]));

		for(final FirmanteInfo firNfo:listaFirmantes){
			if(!lstCodUsu.contains(firNfo.getCodUsuario())){
				firNfo.setsSnMsgacp(arrMsg[0]);
			} else {
				firNfo.setsSnMsgacp("N");
			}
		}
		return arrMsg[1];
	}


	@Override
	public void mergeMsgAcepCodUsuario(final String codAplicacion, final String codUsuario, final List<FicheroPdteFirma> lstFichPteFirma) throws ExcepcionEjecucionAplicacion{

		final Set<String> setCodTipoOrden = new HashSet<String>(8);
		for(final FicheroPdteFirma firNfo:lstFichPteFirma){ //Para eliminar los duplicados.
			setCodTipoOrden.add(firNfo.getsCodTipoOrden());
		}
		final String[] arrCodTipoOrden = setCodTipoOrden.toArray(new String[setCodTipoOrden.size()]);
		// Verificamos si esta en la tabla ont y que valores tiene en la tabla ppa
		final List<String[]> lstCodMsg = servicioFirmasDao.findMensajeAceptacion(codAplicacion, arrCodTipoOrden);

		final List<String> lstCodTipOrd = servicioFirmasDao.findTipOrdFirmaPrevia(codUsuario,arrCodTipoOrden);

		for(final FicheroPdteFirma firNfo:lstFichPteFirma){
			for(final String[] arrCodMsg:lstCodMsg){
				if(firNfo.getsCodTipoOrden().equals(arrCodMsg[2])){
					firNfo.setCodigoMensajeAceptacion(arrCodMsg[1]);
					if(!lstCodTipOrd.contains(firNfo.getsCodTipoOrden())){
						firNfo.setMensajeAceptacion(arrCodMsg[0]);
					} else {
						firNfo.setMensajeAceptacion("N");
					}
					break;
				}
			}
		}
	}

}
